<?php

namespace Modules\DataAnalysis\Http\Controllers\Admin;

use App\Exceptions\BusinessException;
use App\Helpers\CodeResponse;
use App\Helpers\QueryBuilder;
use App\Http\Controllers\Admin\ApiController;
use App\Http\Resources\BaseResource;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\DB;
use Modules\DataAnalysis\Entities\Comment;
use Modules\DataAnalysis\Entities\CommentPhrase;
use Modules\DataAnalysis\Entities\CommentPhraseSpider;
use Modules\DataAnalysis\Entities\CommentSpider;
use Modules\DataAnalysis\Entities\Setting;
use Modules\DataAnalysis\Entities\Video;
use Modules\DataAnalysis\Entities\VideoSpider;

class VideosController extends ApiController
{
    /**
     * Display a listing of the resource.
     * @return Renderable
     */
    public function index()
    {
        // 系统设置
        $settings = Setting::query()->get();
        $score_line = $settings->where('key', 'score_line')->first()->value;

        $query = Video::query()->withCount([
            'comments',
            'comments as positive_comments' => function ($q) use ($score_line) {
                $q->where('score', '>=', $score_line);
            },
            'comments as passive_comments' => function ($q) use ($score_line) {
                $q->where('score', '<', $score_line);
            }
        ]);
        $data = QueryBuilder::for($query)
            ->fields()
            ->filters(['title', 'nickname'])
            ->includes()
            ->sorts()
            ->page();
        return $this->success(BaseResource::collection($data));
    }

    /**
     * 这里写成模拟实现数据采集分析（从数据采集分析后存入的表中复制数据到业务系统相关表中）
     * @param Request $request
     * @return Renderable
     */
    public function store(Request $request)
    {
        $video_ids = Video::query()->select('id')->get()->pluck('id')->toArray();
        $video_spider_ids = VideoSpider::query()->select('id')->get()->pluck('id')->toArray();

        // 两个数组的差集 得到在 videos 表中没有但 video_spiders 表中有的 id
        $spider_ids = array_diff($video_spider_ids, $video_ids);
        if (count($spider_ids) == 0) {
            throw new BusinessException(CodeResponse::REJECT_OPERATION, "只能采集这么多啦~");
        }
        // 从 $spider_ids 中随机取一个 id 模拟采集到 videos 表及相关表中
        $spider_id = $spider_ids[array_rand($spider_ids)];

        // 复制 video_spiders 表中 id = $spider_id 的数据到 videos 表中
        $video_spider_data = VideoSpider::find($spider_id)->toArray();
        unset($video_spider_data['created_at'], $video_spider_data['updated_at']);

        $video_data = DB::transaction(function () use ($video_spider_data) {
            $video_data = Video::query()->create($video_spider_data);

            // 复制对应评论
            $comment_spiders = CommentSpider::query()->where('video_id', $video_spider_data['id'])->get();
            foreach ($comment_spiders as $value) {
                Comment::query()->create(collect($value->toArray())->except(['created_at', 'updated_at'])->toArray());
            }

            // 复制视频评论的分词数据
            $comment_phrase_spiders = CommentPhraseSpider::query()->where('video_id', $video_spider_data['id'])->get();
            foreach ($comment_phrase_spiders as $value) {
                $phrases = !empty($value->phrase) ? json_decode(str_replace("'", '"', $value->phrase), true) : [];
                foreach ($phrases as $phrase) {
                    if (mb_strlen($phrase) > 1) {
                        CommentPhrase::query()->create([
                            'video_id' => $value->video_id,
                            'comment_id' => $value->comment_id,
                            'phrase' => $phrase,
                        ]);
                    }
                }
            }

            return $video_data;
        });

        // 这里随机延时几秒 模拟真实采集数据时采集速度较慢的情况
        // sleep(rand(2, 5));

        return $this->success($video_data);
    }

    /**
     * Remove the specified resource from storage.
     * @param int $id
     * @return Renderable
     */
    public function destroy(Video $video)
    {
        DB::transaction(function () use ($video) {
            $video->comments()->delete();
            $video->comment_phrases()->delete();
            $video->delete();
        });

        return $this->noContent();
    }

    /**
     * Remove the specified resource from storage.
     * @param int $id
     * @return Renderable
     */
    public function deleteAll()
    {
        $videos = Video::query()->get();
        DB::transaction(function () use ($videos) {
            foreach ($videos as $video) {
                $video->comment_phrases()->delete();
                $video->comments()->delete();
                $video->delete();
            }
        });

        return $this->noContent();
    }
}
